///////////////////////////////////////////////////////////////////////////////
// Name:        wrdbg.h
// Purpose:     debug C type code
// Author:      Bright Li
// Modified by:
// Created:     2018-09-03
// Version:     [0.3.3]
// RCS-ID:      $$
// Copyright:   (c) Bright Li
// Licence:
///////////////////////////////////////////////////////////////////////////////

#pragma once
#ifndef _WRD_DEBUG_H__
#define _WRD_DEBUG_H__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <setjmp.h>

/*-----------------------------------------------------------------*\
    Self Define Debugging-Macro
\*-----------------------------------------------------------------*/
// If you need to SHOW the output,
// You should add #define __WRD_DEBUG__ 1, before #include "wrdbg.h"

#ifndef __WRD_DEBUG__
  #define __WRD_DEBUG__ 1
#endif

// Python-like print funcion
#define _print(note, ...) \
    if(__WRD_DEBUG__) \
    printf("-- DEBUG -->> " note "\n",  ##__VA_ARGS__)

// 支持多变量打印
#define _print_var(...) \
{    void *stopper_for_apply = (int[]){0};  \
    char **list_for_apply = (char*[]){__VA_ARGS__, stopper_for_apply};  \
    for(int i=0; list_for_apply[i] != stopper_for_apply; i++)  \
        _print("%s", list_for_apply[i]);}

// C-type Exception functions
#define Except_Declare(ModuleName) \
    extern struct ExceptLink Except_##ModuleName; \
    enum ExceptEnum_##ModuleName

#define Except_Implement(ModuleName) \
    struct ExceptLink Except_##ModuleName; \
    static void _raise(int err_no, const char* description){ \
        _raise_c(err_no, description, &Except_##ModuleName); }

// 可配置选项
#define ExceptLink_Desciption_Length 64

// 全局宏定义 & 函数声明
struct ExceptLink{
    jmp_buf jmp_buffer;
    int err;
    char description[ExceptLink_Desciption_Length];
#ifdef __cplusplus
    ExceptLink(){ err = 0;
        memset(description, 0, ExceptLink_Desciption_Length); }
    void what(){ printf("%s\n", description); }
#endif
};

void _raise_c(int err_no, const char* description, struct ExceptLink *module);
#define _what(ExceptLink) \
    printf(#ExceptLink" : %s, Err_No : %d\n", ExceptLink.description, ExceptLink.err);

#define TRY(module_except) \
    { int jmp_err = setjmp(module_except.jmp_buffer); \
    if (0 == jmp_err)

#define CATCH(err_enum) \
    else if (err_enum == jmp_err)

#define ELSE else
#define ENDTRY }


/*-----------------------------------------------------------------*\
    C++ Macro
\*-----------------------------------------------------------------*/
#ifdef __cplusplus

#define _throw(note) \
{   char* morefunc; \
    asprintf(&morefunc, "-- EXCEPT -->> %s :: %s", __FUNCTION__, note); \
    throw morefunc; \
    free(morefunc); }

#include <string>
// std::string _format(...){
//     return string()
// }

#define _format(str_obj, format, ...) \
{   char* pstr; \
    asprintf(&pstr, format, ##__VA_ARGS__); \
    str_obj.assign(pstr); \
    free(pstr); }

#endif  // __cplusplus

#endif  // _WRD_DEBUG_H__
